package cn.kgc.shiroday03.aop;

import cn.kgc.shiroday03.annotations.OperationLog;
import cn.kgc.shiroday03.commons.Operation;
import cn.kgc.shiroday03.entity.LogInfo;
import cn.kgc.shiroday03.service.LogInfoService;
import cn.kgc.shiroday03.util.IpUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @Author: 课工场
 * @Version: v1.0  2023/6/13
 * @Description: 操作日志的通知类
 */
@Component
@Aspect
public class OperationAspect {

    @Autowired
    private LogInfoService logInfoService;

    @Pointcut("@annotation(cn.kgc.shiroday03.annotations.OperationLog)")
    public void point(){};

    @Around("point()")
    public Object around(ProceedingJoinPoint joinPoint){
        // 日志对象
        LogInfo logInfo = new LogInfo();
        Object proceed = null;
        try {
             //目标方法的执行
             proceed = joinPoint.proceed();
             // 获取用户名
            Subject subject = SecurityUtils.getSubject();
            String principal = (String) subject.getPrincipal();
            logInfo.setUsername(principal);
            //获取目标方法上传递的参数
            Object[] args = joinPoint.getArgs();
            String params = StringUtils.arrayToCommaDelimitedString(args);
            logInfo.setParams(params);
            // 获取方法注解
            MethodSignature methodSignature =(MethodSignature) joinPoint.getSignature();
            Method method = methodSignature.getMethod();
            // 解析方法上是否含有日志注解
            OperationLog annotation = method.getAnnotation(OperationLog.class);
            Operation description = annotation.description();
            String info = description.getInfo();
            logInfo.setDescription(info);

            String model = annotation.model();
            logInfo.setModel(model);

            //  ip  url    request
            ServletRequestAttributes requestAttributes =(ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();

            //资源地址
            String uri = request.getRequestURI();
            logInfo.setUrl(uri);

            String ip = IpUtil.getIp(request);
            logInfo.setIp(ip);
            logInfoService.save(logInfo);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }


        return proceed;
    }


}
